In legacy mainframe computing environments, it is common to find monolithic applications including thousands and even tens of thousands of individual programs all running together in a very monolithic structure in a single operating environment. This monolithic structure of programs may represent substantial investments of time and resources in the development of their underlying code (up to several thousands of man-years), and the interdependent nature of the software programs makes translating or migrating the code from one computer environment very difficult.
Legacy program files may be compiled, assembled and linked with the constraint to run only on a processor of a specific architecture and instruction set, often referred to as part of a legacy system or legacy platform.
FIG. 1A depicts the elements of a legacy platform (100) that uses hypervisor virtualization. The system hardware (10) may include, for example, a mainframe computer running a hypervisor (30), often as a virtual machine monitor (z/VM), to provide as set of fully isolated virtual machines (70), each with its own guest Operating System (OS) (20), and associated OS libraries (80) in which programs are typically run. The hypervisor (30) provides a management platform that partitions the resources of the host machine into the set of virtual or guest machines (70) that can operate independently within the legacy system. A guest operating system (40), or multiple guest operating systems (40) are installed in the virtual machines. A set of binaries and library programs (50), and one or more applications (60) then run on a given virtual machine. Like a physical machine, the virtual machine has associated state information, can be backed up or restored, and may be assigned dedicated system resources. The starting up and tearing down of a virtual machine in a hypervisor system requires considerable overhead, and for this reason, when established, virtual machines typically persist for considerable run times.
FIG. 1B depicts an example of a container management system (110). The hardware (15) of the container system may be a physical server or a cluster of physical servers, which may, for example, be X86-based computers. The host operating system kernel (25) of the system, such as Linux, is shared by the platform, and a set of containers (75) are enabled through a container management system (35) such as Docker. In particular, the namespace and group functionality of the Linux kernel may be used for containerization. Container management systems may be provided as wrappers around the kernel functionalities and allow for container management, such as deployment.
Other container management systems such as the Amazon ACS, Azure Container Service, Cloud Foundry Diego, CoreOS Fleet, Docker Swarm, Google Container Engine, or Mesosphere Marathon container management system, or other container management and orchestration system can be used. The container management system (35) and a set of shared operating system libraries (85) provide a platform in which the set of containers (75) may execute. For example, some low-level operating system libraries 85, such as those used for basic file input/output (I/O) functions, may be shared by all containers through the operating system kernel or container management system rather than resident in individual containers.
As in the case of the virtual machine, a set of binaries and library programs (55), and one or more applications (65) run in a set of containers (75). By way of example, a library that provides web access services, such as http protocol, may only be needed in some applications and not others, and would thus be included in the library programs (55) when required for a specific application service, but omitted from the library programs (55) of a container with only applications that never use a web access service.
Compared to a virtual machine, a container is a relatively lightweight construct, and is not burdened with the overhead of its own full operating system and all of the state information associated with a physical or virtual machine. Consequently, the starting up and tearing down of a container requires little overhead, which makes the deployment and termination of containers an effective technique for application upgrade, dynamic load balancing and resource allocation within a cluster.
In particular, virtual machines have their own operating system, file system, processor(s), network adapters, and associated storage volumes. The fact that they run a guest operating system over a hypervisor makes virtual machines a heavyweight process, with the overhead of running two operating systems (hypervisor+guest operating system) on top of each other, that cannot be easily launched and terminated, to accommodate changing demand for application services. Containers, on the other hand, share core operating system functions through kernel direct access and other physical resources including storage volumes. Storage volumes are typically resident on fixed disk drives, but may also reside in other mass storage including flash drives, tape, or other fixed or removable storage media. Although the behavior of different container may differ based on binary and library programs that are incorporated into the image loaded into those particular containers, the use of shared operating system services significantly reduces the overhead associated with each individual instance of a container. For this reason, containers are lightweight, relative to virtual machines, which makes the instantiation and termination of containers in response to application demands more feasible. Indeed, in the case of, for example, the Kubernetes container management system running Docker, a container can be launched in a fraction of a second. For that reason, large deployments may launch and terminate several thousands of those containers every second.
Container management systems may also include pods. A pod is a deployment unit in a container system that includes one or more containers that are deployed together on the same host or cluster. In some container management systems, such as Kubernetes, containers in a pod share the same network namespace and port space. Additionally, shared volumes of storage that are attached to the pod may be mounted in one or more of the pod's containers.
A standard Linux distribution includes tens (even hundreds) of thousands of individual files, and, depending on the application for which such a system is used, may be combined with thousands of additional system packages that add functionality to the platform. Examples of such packages include the Apache web server, Java virtual machine, PostgreSQL, or other packages to provide database or language support and the like. These packages include program code and metadata describing the packages and dependencies between packages and other libraries. Shared libraries can be used by dynamically linked packages to provide tremendous functionality, but can greatly increase the footprint of the Linux image, and the complexity of system administration. A minimal instance of Linux that incorporates very few packages may occupy only a few megabytes of memory. On the other hand, a large installation with many packages used to support, for example, a large-scale application web-server with advanced database services may occupy hundreds of megabytes of storage, or even more. The administration of Linux-based platforms often includes the use of package manager software to manage the dependencies between packages and libraries and the recurring upgrades of those libraries and packages. A large image serving multiple targets at once is more complex to manage than a simple one.
Microservices are typically small, autonomous services that can collaborate tightly together to provide the functionality of an application. The autonomous nature of microservices enables them to be deployed independently of each other as isolated services, that may communicate with other services through network calls. A set of closely related microservices, or microservices that, in their operation, share access to a common volume, may be deployed within the same pod. A microservice architecture offers important advantages of manageability, availability, scalability, and deployability on clustered systems. However, the monolithic nature of many legacy applications, makes translating such monolithic applications into sets of minimally interdependent microservices a difficult and manually intensive task. Further complicating the problem, legacy monolithic applications written in Cobol and compiled to run on legacy architectures such as MVS or z/OS with their proprietary APIs cannot generally be exported from the legacy architecture and executed onto a Linux or other operating system or cluster, especially when based on x86 servers. due to differences in instruction sets and APIs.
More generally, systems that translate application code from one operating environment to another, whether through emulation, cross-compiling, transcoding, or a hybrid approach can be developed to enable the execution of a compiled legacy program to run on a guest operating system using a different underlying architecture. However, such systems tend themselves to be large programs that do not easily scale, which is particularly problematic in the case of executing applications that perform high transaction volumes. Additionally, emulation or transcoding systems lend themselves to be monolithic applications because, in order to be useful, the emulator or transcoder must be capable of executing an unknown subset of the possible instructions of the legacy environment in the guest environment.